home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 1999 August / SGI Freeware 1999 August.iso / dist / fw_xemacs.idb / usr / freeware / lib / xemacs-20.4 / lisp / packages / lazy-lock.el.z / lazy-lock.el
Encoding:
Text File  |  1998-05-21  |  49.8 KB  |  1,109 lines

  1. ;;; lazy-lock.el --- Lazy demand-driven fontification for fast Font Lock mode.
  2.  
  3. ;; Copyright (C) 1994, 1995 Free Software Foundation, Inc.
  4.  
  5. ;; Author: Simon Marshall <simon@gnu.ai.mit.edu>
  6. ;; X-Modified-By: Ben Wing <ben@666.com>
  7. ;; Maintainer: XEmacs Development Team
  8. ;; Keywords: faces files
  9. ;; Version: 1.14
  10.  
  11. ;; LCD Archive Entry:
  12. ;; lazy-lock|Simon Marshall|simon@gnu.ai.mit.edu|
  13. ;; Lazy Font Lock mode (with fast demand-driven fontification).|
  14. ;; 13-Oct-95|1.14|~/modes/lazy-lock.el.Z|
  15.  
  16. ;; The archive is archive.cis.ohio-state.edu in /pub/gnu/emacs/elisp-archive.
  17.  
  18. ;;; This file is part of GNU Emacs.
  19.  
  20. ;; GNU Emacs is free software; you can redistribute it and/or modify
  21. ;; it under the terms of the GNU General Public License as published by
  22. ;; the Free Software Foundation; either version 2, or (at your option)
  23. ;; any later version.
  24.  
  25. ;; GNU Emacs is distributed in the hope that it will be useful,
  26. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  27. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  28. ;; GNU General Public License for more details.
  29.  
  30. ;; You should have received a copy of the GNU General Public License
  31. ;; along with GNU Emacs; see the file COPYING.  If not, write to the
  32. ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  33. ;; Boston, MA 02111-1307, USA.
  34.  
  35. ;;; Synched up with: Divergent from Official Version.
  36.  
  37. ;;; Commentary:
  38.  
  39. ;; This version of Lazy Lock has special modifications for XEmacs by Ben Wing
  40. ;; that have never been merged into the official version.
  41.  
  42. ;; Purpose:
  43. ;;
  44. ;; To make visiting buffers in `font-lock-mode' faster by making fontification
  45. ;; be demand-driven and stealthy.
  46. ;; Fontification only occurs when, and where, necessary.
  47. ;;
  48. ;; See caveats and feedback below.  See also the defer-lock and fast-lock
  49. ;; packages.  (But don't use lazy-lock.el and fast-lock.el at the same time!)
  50.  
  51. ;; Installation:
  52. ;; 
  53. ;; Put this file somewhere where Emacs can find it (i.e., in one of the paths
  54. ;; in your `load-path'), `byte-compile-file' it, and put in your ~/.emacs:
  55. ;;
  56. ;; (autoload 'turn-on-lazy-lock "lazy-lock"
  57. ;;   "Unconditionally turn on Lazy Lock mode.")
  58. ;;
  59. ;; (add-hook 'font-lock-mode-hook 'turn-on-lazy-lock)
  60. ;;
  61. ;; Start up a new Emacs and use font-lock as usual (except that you can use the
  62. ;; so-called "gaudier" fontification regexps on big files without frustration).
  63. ;;
  64. ;; In a buffer (which has `font-lock-mode' enabled) which is at least
  65. ;; `lazy-lock-minimum-size' characters long, only the visible portion of the
  66. ;; buffer will be fontified.  Motion around the buffer will fontify those
  67. ;; visible portions that were not previous fontified.  If the variable
  68. ;; `lazy-lock-hide-invisible' is non-nil, redisplay will be delayed until after
  69. ;; fontification.  Otherwise, text that has not yet been fontified is displayed
  70. ;; in `lazy-lock-invisible-foreground'.
  71. ;;
  72. ;; If stealth fontification is enabled, fontification will occur in invisible
  73. ;; parts of the buffer after `lazy-lock-stealth-time' seconds of idle time.
  74.  
  75. ;; Advanced Use:
  76. ;;
  77. ;; You can also do fancy things with `advice'.  For example, to fontify when
  78. ;; dragging the scroll-bar in Emacs, you could put in your ~/.emacs:
  79. ;;
  80. ;; (autoload 'lazy-lock-post-command-fontify-windows "lazy-lock")
  81. ;;
  82. ;; (defadvice scroll-bar-drag-1 (after fontify-window activate compile)
  83. ;;   (let ((lazy-lock-walk-windows nil) (lazy-lock-hide-invisible nil))
  84. ;;     (lazy-lock-post-command-fontify-windows)))
  85. ;;
  86. ;; Or to fontify when the Debugger pops up a source code window:
  87. ;;
  88. ;; (autoload 'lazy-lock-fontify-walk-windows "lazy-lock")
  89. ;;
  90. ;; (defadvice gud-display-line (after fontify-window activate compile)
  91. ;;   (let ((lazy-lock-walk-windows t) (lazy-lock-hide-invisible t))
  92. ;;     (lazy-lock-fontify-walk-windows)))
  93. ;;
  94. ;; Scott Byer <byer@mv.us.adobe.com> suggested this to fontify the visible part
  95. ;; of an insertion only:
  96. ;;
  97. ;; (defvar lazy-lock-insert-commands
  98. ;;   '(yank yank-pop clipboard-yank hilit-yank hilit-yank-pop 
  99. ;;     mail-yank-original mouse-yank-at-click mouse-yank-secondary
  100. ;;     yank-rectangle)
  101. ;;   "A list of insertion commands.")
  102. ;;
  103. ;; (defadvice font-lock-after-change-function (around fontify-insertion
  104. ;;                                             activate compile)
  105. ;;   (if (or (not (memq this-command lazy-lock-insert-commands))
  106. ;;       (and (pos-visible-in-window-p beg) (pos-visible-in-window-p end)))
  107. ;;       ad-do-it
  108. ;;     (let ((this-command 'ignore))
  109. ;;       (put-text-property beg end 'fontified nil)
  110. ;;       (lazy-lock-fontify-window))))
  111. ;;
  112. ;; Let me know if you use any other `advice' and I'll put it here.  Thanks.
  113. ;;
  114. ;; These kinds of things with `advice' aren't done automatically because they
  115. ;; cause large packages (advice.el plus bytecomp.el and friends) to be loaded.
  116.  
  117. ;; Caveats:
  118. ;;
  119. ;; Lazy Lock mode does not work efficiently with Outline mode.  This is because
  120. ;; when in Outline mode, although text may be hidden (not visible in the
  121. ;; window), the text is visible to Emacs Lisp code (not surprisingly) and Lazy
  122. ;; Lock fontifies it mercilessly.  Hopefully this will be fixed one day.
  123. ;;
  124. ;; Lazy Lock mode does not fontify windows as they appear:
  125. ;;
  126. ;; 1.  With `query-replace' or `ispell-*', as Lazy Lock only knows about point
  127. ;; motion after the command exits.
  128. ;;
  129. ;; 2.  When displayed by gud.el (the Grand Unified Debugger), as they are
  130. ;; displayed via a process sentinel.  See `Advanced Use' above.
  131. ;;
  132. ;; 3.  In XEmacs 19.12, when the last command was invoked via a mouse event,
  133. ;; because of a bug/feature in/of `sit-for'.
  134. ;;
  135. ;; 4.  In other random situations that I don't know about (yet).
  136. ;;
  137. ;; If you have `lazy-lock-hide-invisible' you may notice that redisplay occurs
  138. ;; before fontification regardlessly.  This is due to other packages sitting on
  139. ;; `post-command-hook' and provoking redisplay.  If you use these packages, you
  140. ;; can't use `lazy-lock-hide-invisible'.
  141. ;;
  142. ;; If you have `lazy-lock-hide-invisible' and use scrollbar scrolling using
  143. ;; Emacs 19, hidden text will not be fontified as it becomes visible.  It is
  144. ;; expected that Emacs 19 will provide the necessary hooks in future, to solve
  145. ;; this problem and the problem above.
  146. ;;
  147. ;; Unless otherwise stated, "Emacs 19.X" means versions up to and including X.
  148. ;;
  149. ;; In Emacs 19.25, one `window-start'/`window-end' bug means that if you open a
  150. ;; file in another frame (such as via `find-tag-other-frame'), the whole buffer
  151. ;; is fontified regardless.  Upgrade!
  152. ;;
  153. ;; In Emacs 19.25, fontification by stealth is turned off because of a fatal
  154. ;; bug in `previous-single-property-change'.  Upgrade!
  155. ;;
  156. ;; In Emacs 19.28, if you see a message in the minibuffer of the form
  157. ;;  "Fontifying window... done.  (Restarted in foo.c)"
  158. ;; it means the Garbage Collector has marked some (subsequently used) text
  159. ;; properties.  Lazy Lock attempts to recover the situation by restarting in
  160. ;; that buffer.  Unfortunately, that buffer will be left in a writable and
  161. ;; modified state.  Also, other windows may not be fontified when this happens.
  162. ;; To reduce the frequency of this bug occuring, increase in your ~/.emacs the
  163. ;; value of `gc-cons-threshold' to, say, 1Meg, e.g.:
  164. ;;
  165. ;; (setq gc-cons-threshold (* 1024 1024))
  166. ;;
  167. ;; The solution is to upgrade!  (With thanks to Kevin Broadey for help here.)
  168. ;;
  169. ;; For XEmacs 19.11 and Lucid Emacs 19.10 users, lazy-lock sort-of works.
  170. ;; There are bugs in text property and point/window primatives.  Upgrade!
  171.  
  172. ;; Feedback:
  173. ;;
  174. ;; Feedback is welcome.
  175. ;; To submit a bug report (or make comments) please use the mechanism provided:
  176. ;;
  177. ;; M-x lazy-lock-submit-bug-report RET
  178.  
  179. ;; History:
  180. ;;
  181. ;; 0.01--1.00:
  182. ;; - Changed name from fore-lock to lazy-lock.  Shame though.
  183. ;; - Dropped `advice'-wrapping completely.  Ask me if you're interested in it.
  184. ;; - Made `lazy-lock-mode' ignore `post-command-hook' and `buffer-file-name'.
  185. ;; - Made `lazy-lock-fontify-window' check `lazy-lock-mode' and `this-command'.
  186. ;; - Made `lazy-lock-fontify-window' redisplay via `sit-for'.
  187. ;; - Added `lazy-lock-minimum-size' to control `lazy-lock-mode'.
  188. ;; 1.00--1.01:
  189. ;; - Added `lazy-lock-fontify-buffer'.
  190. ;; - Made `lazy-lock-fontify-window' ignore `lazy-lock-mode'.
  191. ;; - Made `lazy-lock-fontify-window' suspicious of `window-' favourites again.
  192. ;; - Added `lazy-lock-delay-commands' (idea from William G. Dubuque).
  193. ;; - Added `lazy-lock-ignore-commands' for completeness.
  194. ;; - Added `lazy-lock-continuity-time' for normal input delay.
  195. ;; 1.01--1.02:
  196. ;; - Made `lazy-lock-fontify-window' cope with multiple unfontified regions.
  197. ;; - Made `lazy-lock-mode' remove `fontified' properties if turned off.
  198. ;; - Made `lazy-lock-fontify-window' fontify by lines.
  199. ;; - Added `lazy-lock-cache-position' buffer local to detect visibility change.
  200. ;; - Added `lazy-lock-post-command-hook' to do the waiting.
  201. ;; - Made `lazy-lock-fontify-window' just do the fontification.
  202. ;; - Made `lazy-lock-mode' append `lazy-lock-post-command-hook'.
  203. ;; - Added `lazy-lock-walk-windows' to hack multi-window motion.
  204. ;; - Made `lazy-lock-post-command-hook' `walk-windows' if variable is non-nil.
  205. ;; - Removed `lazy-lock-ignore-commands' since insertion may change window.
  206. ;; - Added `lazy-lock-fontify-stealthily' and `lazy-lock-stealth-time'.
  207. ;; - Made `lazy-lock-post-command-hook' use them.
  208. ;; 1.02--1.03:
  209. ;; - Made `lazy-lock-fontify-stealthily' do `forward-line' not `previous-line'.
  210. ;; - Made `lazy-lock-fontify-stealthily' `move-to-window-line' first.
  211. ;; - Made `lazy-lock-fontify-stealthily' use `text-property-any' for region.
  212. ;; - Made `lazy-lock-post-command-hook' loop on `lazy-lock-fontify-stealthily'.
  213. ;; 1.03--1.04:
  214. ;; - Made `lazy-lock-mode' reset `lazy-lock-cache-position'.
  215. ;; - Made `lazy-lock-post-command-hook' `widen' for `if' `text-property-any'.
  216. ;; - Made `lazy-lock-fontify-stealthily' return `text-property-any'.
  217. ;; - Added `lazy-lock-percent-fontified' for a/be-musement.
  218. ;; - Made `lazy-lock-post-command-hook' use it.
  219. ;; - Made `lazy-lock-mode' use `make-local-hook' etc. if available.
  220. ;; - Made `lazy-lock-mode' use `before-revert-hook' and `after-revert-hook'.
  221. ;; - Made `lazy-lock-post-command-hook' protect `deactivate-mark'.
  222. ;; - Adds `lazy-lock-post-command-hook' globally to `post-command-hook'.
  223. ;; 1.04--1.05:
  224. ;; - Made `lazy-lock-mode' test `make-local-hook' not `emacs-minor-version'.
  225. ;; 1.05--1.06:
  226. ;; - Added `lazy-lock-ignore-commands' for commands that leave no event but do.
  227. ;; - Made `lazy-lock-post-command-hook' check `lazy-lock-ignore-commands'.
  228. ;; 1.06--1.07:
  229. ;; - Removed `before-revert-hook' and `after-revert-hook' use.
  230. ;; 1.07--1.08:
  231. ;; - Added `lazy-lock-submit-bug-report'.
  232. ;; - Made `lazy-lock-post-command-hook' check `executing-macro'.
  233. ;; - Made it sort-of/almost work for XEmacs (help from Jonas Jarnestrom).
  234. ;; - XEmacs: Fix `text-property-not-all' (fix based on fast-lock.el 3.05 fix).
  235. ;; - XEmacs: Set `font-lock-no-comments' and alias `frame-parameters'.
  236. ;; - Made `byte-compile-warnings' omit `unresolved' on compilation.
  237. ;; - Made `lazy-lock-post-command-hook' protect `buffer-undo-list'.
  238. ;; - Moved `deactivate-mark' and `buffer-undo-list' protection to functions.
  239. ;; - Added `lazy-lock-invisible-foreground' (idea from Boris Goldowsky).
  240. ;; - XEmacs: Fix to use `text-property-not-all' t, not `text-property-any' nil.
  241. ;; - Made `lazy-lock-percent-fontified' return `round' to an integer.
  242. ;; - XEmacs: Fix `text-property-any' (fix and work around for a bug elsewhere).
  243. ;; - XEmacs: Fix `lazy-lock-submit-bug-report' for reporter.el & vm-window.el.
  244. ;; - XEmacs: Made `lazy-lock-fontify-window' loop `while' `<' not `/='.
  245. ;; - Use `font-lock-after-change-function' to do the fontification.
  246. ;; 1.08--1.09:
  247. ;; - Made `lazy-lock-post-command-hook' protect with `condition-case'.
  248. ;; - Made `lazy-lock-cache-start' to cache `window-start'.
  249. ;; - Made `lazy-lock-fontify-window' check and cache `lazy-lock-cache-start'.
  250. ;; - Renamed `lazy-lock-cache-position' to `lazy-lock-cache-end'.
  251. ;; - XEmacs: Fix for `font-lock-after-change-function'.
  252. ;; - Adds `lazy-lock-post-command-hook' globally to `window-setup-hook'.
  253. ;; 1.09--1.10:
  254. ;; - Made `buffer-file-name' be `let' to prevent supersession (Kevin Broadey).
  255. ;; - Made `lazy-lock-submit-bug-report' `require' reporter (Ilya Zakharevich).
  256. ;; - Made `lazy-lock-mode' and `turn-on-lazy-lock' succeed `autoload' cookies.
  257. ;; - Added `lazy-lock-fontify-walk-windows' for walking window fontification.
  258. ;; - Added `lazy-lock-fontify-walk-stealthily' for walking stealth.
  259. ;; - Removed `move-to-window-line' from `lazy-lock-fontify-stealthily'.
  260. ;; - Made `lazy-lock-percent-fontified' use `truncate' rather than `round'.
  261. ;; - Added other `*-argument' to `lazy-lock-ignore-commands' (Kevin Broadey).
  262. ;; - Made `lazy-lock-fontify-stealthily' not assume buffer is part `fontified'.
  263. ;; - Emacs: Fix for `font-lock-fontify-region'.
  264. ;; - Made `lazy-lock-post-command-hook' check for minibuffer (Kevin Broadey).
  265. ;; - Added `lazy-lock-stealth-nice' for niceness during stealth fontification.
  266. ;; - Added `lazy-lock-stealth-lines' for chunks of stealth fontification.
  267. ;; 1.10--1.11: incorporated hack by Ben Wing from William Dubuque's fontifly.el
  268. ;; - Made `lazy-lock-fontify-stealthily' see a non `fontified' preceding line.
  269. ;; - XEmacs: Fix `text-property-any' and `text-property-not-all' (Ben Wing).
  270. ;; - XEmacs: Fix `lazy-lock-continuity-time' (Ben Wing).
  271. ;; - Added awful `lazy-lock-running-xemacs-p' (Ben Wing).
  272. ;; - Made loading set `emacs-minor-version' if it's not bound.
  273. ;; - Added `lazy-lock-hide-invisible' to control redisplay.
  274. ;; - Made `lazy-lock-post-command-hook' use it in `sit-for' (Ben Wing).
  275. ;; - Made `lazy-lock-fontify-window' move relative to `end-of-line' if non-nil.
  276. ;; - Added `lazy-lock-fontify-region' so packages can ensure fontification.
  277. ;; - Made `lazy-lock-fontify-walk-stealthily' do stealth widening.
  278. ;; - Made `lazy-lock-fontify-stealthily' always do adjacent preceding regions.
  279. ;; - Added `lazy-lock-after-fontify-buffer'.
  280. ;; - XEmacs: Removed `font-lock-no-comments' incompatibility code.
  281. ;; - Removed `lazy-lock-delay-time' and `lazy-lock-delay-commands'.
  282. ;; - Removed `lazy-lock-post-command' and split the functionality.
  283. ;; - Adds `lazy-lock-post-command-fontify-windows' on first.
  284. ;; - Adds `lazy-lock-post-command-fontify-stealthily' on last.
  285. ;; - Made `lazy-lock-mode' ensure both first and last on `post-command-hook'.
  286. ;; - Made `lazy-lock-mode' ensure `font-lock-mode' is on.
  287. ;; - Wrap `lazy-lock-post-command-fontify-stealthily' for errors (David Karr).
  288. ;; - Added `calcDigit-key' to `lazy-lock-ignore-commands' (Bob Glickstein).
  289. ;; - Wrap `lazy-lock-running-xemacs-p' with `eval-and-compile' (Erik Naggum).
  290. ;; - XEmacs: Fix use of `previous-single-property-change' (Jim Thompson).
  291. ;; - XEmacs: Fix `next-single-property-change' fix for 19.11 (Jim Thompson).
  292. ;; - Added `lazy-lock-post-resize-fontify-windows' to fontify on resizing.
  293. ;; - Adds globally to `window-size-change-functions'.
  294. ;; - Added `lazy-lock-post-setup-fontify-windows' to fontify after start up.
  295. ;; - Adds globally to `window-setup-hook'.
  296. ;; - Made `lazy-lock-post-command-fontify-windows' check for `input-pending-p'.
  297. ;; - Made `save-selected-window' to restore the `selected-window'.
  298. ;; - Use `save-selected-window' rather than `save-window-excursion'.
  299. ;; 1.11--1.12:
  300. ;; - Made `lazy-lock-post-command-fontify-windows' do `set-buffer' first.
  301. ;; - Made `lazy-lock-fontify-stealthily' respect narrowing before point.
  302. ;; - Added `lazy-lock-post-setup-ediff-control-frame' for Ediff control frame.
  303. ;; - Adds globally to `ediff-after-setup-control-frame-hooks'.
  304. ;; - Wrap `save-selected-window' with `save-excursion' for `current-buffer'.
  305. ;; 1.12--1.13:
  306. ;; - XEmacs: Add `lazy-lock-after-fontify-buffer' to the Font Lock hook.
  307. ;; - Made `buffer-file-truename' also wrapped for supersession (Rick Sladkey).
  308. ;; - Made `font-lock-beginning-of-syntax-function' wrapped for fontification.
  309. ;; - Added `lazy-lock-stealth-verbose' (after harassment from Ben Wing).
  310. ;; - XEmacs: Made `font-lock-verbose' wrapped for stealth fontification.
  311. ;; 1.13--1.14:
  312. ;; - Wrap `lazy-lock-colour-invisible' for `set-face-foreground' (Jari Aalto).
  313.  
  314. (require 'font-lock)
  315.  
  316. (eval-when-compile
  317.   ;; Only `require' so `ediff-multiframe-setup-p' is expanded at compile time.
  318.   (condition-case nil (require 'ediff) (file-error))
  319.   ;; Well, shouldn't Lazy Lock be as lazy as possible?
  320.   ;(setq byte-compile-dynamic t byte-compile-dynamic-docstrings t)
  321.   ;; Shut Emacs' byte-compiler up (cf. stop me getting mail from users).
  322.   (setq byte-compile-warnings '(free-vars callargs redefine)))
  323.  
  324. (defun lazy-lock-submit-bug-report ()
  325.   "Submit via mail a bug report on lazy-lock.el."
  326.   (interactive)
  327.   (require 'reporter)
  328.   (let ((reporter-prompt-for-summary-p t))
  329.     (reporter-submit-bug-report "simon@gnu.ai.mit.edu" "lazy-lock 1.14"
  330.      '(lazy-lock-walk-windows lazy-lock-continuity-time
  331.        lazy-lock-stealth-time lazy-lock-stealth-nice
  332.        lazy-lock-stealth-lines lazy-lock-stealth-verbose
  333.        lazy-lock-hide-invisible lazy-lock-invisible-foreground
  334.        lazy-lock-minimum-size lazy-lock-ignore-commands)
  335.      nil nil
  336.      (concat "Hi Si.,
  337.  
  338. I want to report a bug.  I've read the `Bugs' section of `Info' on Emacs, so I
  339. know how to make a clear and unambiguous report.  To reproduce the bug:
  340.  
  341. Start a fresh Emacs via `" invocation-name " -no-init-file -no-site-file'.
  342. In the `*scratch*' buffer, evaluate:"))))
  343.  
  344. ;; Let's define `emacs-major-version', `emacs-minor-version', and
  345. ;; `emacs-version>=' if no-one else has.
  346.  
  347. (if (not (boundp 'emacs-major-version))
  348.     (eval-and-compile
  349.       (defconst emacs-major-version
  350.     (progn (or (string-match "^[0-9]+" emacs-version)
  351.            (error "emacs-version unparsable"))
  352.            (string-to-int (match-string 0 emacs-version)))
  353.     "Major version number of this version of Emacs, as an integer.
  354. Warning, this variable did not exist in Emacs versions earlier than:
  355.   FSF Emacs:   19.23
  356.   XEmacs:      19.10")))
  357.  
  358. (if (not (boundp 'emacs-minor-version))
  359.     (eval-and-compile
  360.       (defconst emacs-minor-version
  361.     (progn (or (string-match "^[0-9]+\\.\\([0-9]+\\)" emacs-version)
  362.            (error "emacs-version unparsable"))
  363.            (string-to-int (match-string 1 emacs-version)))
  364.     "Minor version number of this version of Emacs, as an integer.
  365. Warning, this variable did not exist in Emacs versions earlier than:
  366.   FSF Emacs:   19.23
  367.   XEmacs:      19.10")))
  368.  
  369. (if (not (fboundp 'emacs-version>=))
  370.     (eval-and-compile
  371.       (defun emacs-version>= (major &optional minor)
  372.     "Return true if the Emacs version is >= to the given MAJOR and MINOR numbers.
  373.  
  374. The MAJOR version number argument is required, but the MINOR version number
  375. argument is optional.  If the minor version number is not specified (or is the
  376. symbol `nil') then only the major version numbers are considered in the test."
  377.     (if (null minor)
  378.         (>= emacs-major-version major)
  379.       (or (> emacs-major-version major)
  380.           (and (=  emacs-major-version major)
  381.            (>= emacs-minor-version minor))
  382.           )
  383.       ))))
  384.  
  385. ;; Yuck, but we make so much use of this variable it's probably worth it.
  386. (eval-and-compile
  387.   (defconst lazy-lock-running-xemacs-p
  388.     (not (null (save-match-data (string-match "Lucid" emacs-version))))))
  389.  
  390. (defvar lazy-lock-cache-start nil)    ; for window fontifiction
  391. (defvar lazy-lock-cache-end nil)    ; for window fontifiction
  392. (defvar lazy-lock-cache-continue nil)    ; for stealth fontifiction
  393.  
  394. ;;;###autoload
  395. (defvar lazy-lock-mode nil)        ; for modeline
  396.  
  397. ;; User Variables:
  398.  
  399. (defvar lazy-lock-minimum-size (* 25 1024)
  400.   "*If non-nil, the minimum size for buffers.
  401. Only buffers more than this can have demand-driven fontification.
  402. If nil, means size is irrelevant.")
  403.  
  404. (defvar lazy-lock-walk-windows t
  405.   "*If non-nil, fontify windows other than the selected window.
  406. If `all-frames', fontify windows even on other frames.
  407. A non-nil value slows down redisplay.")
  408.  
  409. ;; XEmacs 19.11 and below exercise a bug in the Xt event loop.
  410. (defvar lazy-lock-continuity-time
  411.   (if (or (not lazy-lock-running-xemacs-p) (emacs-version>= 19 12))
  412.       0
  413.     (if (featurep 'lisp-float-type) 0.001 1))
  414.   "*Time in seconds to delay before normal window fontification.
  415. Window fontification occurs if there is no input within this time.")
  416.  
  417. ;; `previous-single-property-change' at `point-min' up to Emacs 19.25 is fatal.
  418. ;; `text-property-any', `text-property-not-all' and
  419. ;; `next-single-property-change' up to XEmacs 19.11 are too broke.
  420. (defvar lazy-lock-stealth-time
  421.   (if (emacs-version>= 19 (if lazy-lock-running-xemacs-p 12 26)) 30)
  422.   "*Time in seconds to delay before beginning stealth fontification.
  423. Stealth fontification occurs if there is no input within this time.
  424. If nil, means no fontification by stealth.")
  425.  
  426. (defvar lazy-lock-stealth-lines
  427.   (cond ((boundp 'font-lock-maximum-decoration)
  428.      (if font-lock-maximum-decoration 75 150))
  429.     ((boundp 'font-lock-use-maximal-decoration)
  430.      (if font-lock-use-maximal-decoration 50 100))
  431.     (t
  432.      50))
  433.   "*If non-nil, the maximum size of a chunk of stealth fontification.
  434. Each iteration of stealth fontification can fontify this number of lines.
  435. To speed up input response during stealth fontification, at the cost of stealth
  436. taking longer to fontify, you could reduce the value of this variable.
  437. If nil, means use `window-height' for the maximum chunk size.")
  438.  
  439. (defvar lazy-lock-stealth-nice (if (featurep 'lisp-float-type) 0.125 1)
  440.   "*Time in seconds to pause during chunks of stealth fontification.
  441. To reduce machine load during stealth fontification, at the cost of stealth
  442. taking longer to fontify, you could increase the value of this variable.")
  443.  
  444. (defvar lazy-lock-stealth-verbose font-lock-verbose
  445.   "*If non-nil, means stealth fontification should show status messages.")
  446.  
  447. (defvar lazy-lock-ignore-commands
  448.   (append
  449.    ;; Standard commands...
  450.    '(universal-argument digit-argument negative-argument
  451.      isearch-other-control-char isearch-other-meta-char)
  452.    ;; And some resulting from non-standard packages...
  453.    (if (fboundp 'calc) '(calcDigit-key)))
  454.   "A list of commands after which fontification should not occur.
  455. To speed up typing response, at the cost of Lazy Lock not fontifying when
  456. insertion causes scrolling, you could add `self-insert-command' to this list.")
  457.  
  458. (defvar lazy-lock-hide-invisible lazy-lock-running-xemacs-p
  459.   "*If non-nil, hide invisible text while it is fontified.
  460. If non-nil, redisplay is delayed until after fontification occurs.  If nil,
  461. text is shown (in `lazy-lock-invisible-foreground') while it is fontified.
  462. A non-nil value slows down redisplay and can slow down cursor motion.")
  463.  
  464. (defvar lazy-lock-invisible-foreground "gray50" 
  465.   "The foreground colour to use to display invisible text.
  466. If nil, the default foreground is used.  If t, the default background is used.
  467. If a string, it should be a colour to use (either its name or its RGB value).
  468. Invisible text is momentarily seen (if `lazy-lock-hide-invisible' is nil) when
  469. scrolling into unfontified regions.")
  470.  
  471. ;; User Functions:
  472.  
  473. ;;;###autoload
  474. (defun lazy-lock-mode (&optional arg)
  475.   "Toggle Lazy Lock mode.
  476. With arg, turn Lazy Lock mode on if and only if arg is positive and the buffer
  477. is at least `lazy-lock-minimum-size' characters long.
  478.  
  479. When Lazy Lock mode is enabled, fontification is demand-driven and stealthy:
  480.  
  481.  - Fontification occurs in visible parts of buffers when necessary.
  482.    Occurs if there is no input after pausing for `lazy-lock-continuity-time'.
  483.  
  484.  - Fontification occurs in invisible parts when Emacs has been idle.
  485.    Occurs if there is no input after pausing for `lazy-lock-stealth-time'.
  486.  
  487. If `lazy-lock-hide-invisible' is non-nil, text is not displayed until it is
  488. fontified, otherwise it is displayed in `lazy-lock-invisible-foreground'.
  489.  
  490. See also variables `lazy-lock-walk-windows' and `lazy-lock-ignore-commands' for
  491. window (scroll) fontification, and `lazy-lock-stealth-lines',
  492. `lazy-lock-stealth-nice' and `lazy-lock-stealth-verbose' for stealth
  493. fontification.
  494.  
  495. Use \\[lazy-lock-submit-bug-report] to send bug reports or feedback."
  496.   (interactive "P")
  497.   (set (make-local-variable 'lazy-lock-mode)
  498.        (and (<= (or lazy-lock-minimum-size 0) (buffer-size))
  499.         (if arg (> (prefix-numeric-value arg) 0) (not lazy-lock-mode))))
  500.   (if (and lazy-lock-mode (not font-lock-mode))
  501.       ;; Turned on `lazy-lock-mode' rather than using `font-lock-mode-hook'.
  502.       (progn
  503.     (add-hook 'font-lock-mode-hook 'turn-on-lazy-lock)
  504.     (font-lock-mode 1))
  505.     (lazy-lock-fixup-hooks)
  506.     ;; Let's get down to business.
  507.     (if (not lazy-lock-mode)
  508.     (let ((modified (buffer-modified-p)) (inhibit-read-only t)
  509.           (buffer-undo-list t)
  510.           deactivate-mark buffer-file-name buffer-file-truename)
  511.       (remove-text-properties (point-min) (point-max) '(fontified nil))
  512.       (or modified (set-buffer-modified-p nil)))
  513.       (if (and (not lazy-lock-hide-invisible) lazy-lock-invisible-foreground)
  514.       (lazy-lock-colour-invisible))
  515.       (set (make-local-variable 'lazy-lock-cache-start) 0)
  516.       (set (make-local-variable 'lazy-lock-cache-end) 0)
  517.       (set (make-local-variable 'font-lock-fontified) t))))
  518.  
  519. ;;;###autoload
  520. (defun turn-on-lazy-lock ()
  521.   "Unconditionally turn on Lazy Lock mode."
  522.   (lazy-lock-mode 1))
  523.  
  524. (if (not (emacs-version>= 19 (if lazy-lock-running-xemacs-p 12 29)))
  525.     ;; We don't need this in Emacs 19.29 or XEmacs 19.12.
  526.     (defun lazy-lock-fontify-buffer ()
  527.       "Fontify the current buffer where necessary."
  528.       (interactive)
  529.       (lazy-lock-fontify-region (point-min) (point-max))))
  530.  
  531. ;; API Functions:
  532.  
  533. (defun lazy-lock-fixup-hooks ()
  534.   ;; Make sure our hooks are correct.
  535.   (remove-hook 'pre-idle-hook 'lazy-lock-pre-idle-fontify-windows)
  536.   (remove-hook 'post-command-hook 'lazy-lock-post-command-fontify-stealthily)
  537.   ;; Make sure our hooks are at the end.  Font-lock in XEmacs installs
  538.   ;; its own pre-idle-hook to implement deferral (#### something that
  539.   ;; should really be merged with this file; or more likely, lazy-lock
  540.   ;; in its entirety should be merged into font-lock).
  541.   (add-hook 'pre-idle-hook 'lazy-lock-pre-idle-fontify-windows t)
  542.   (add-hook 'post-command-hook 'lazy-lock-post-command-fontify-stealthily t)
  543.   ;; Fascistically remove font-lock's after-change-function and install
  544.   ;; our own.  We know better than font-lock what to do.  Otherwise,
  545.   ;; revert-buffer, insert-file, etc. cause full refontification of the
  546.   ;; entire changed area.
  547.   (if lazy-lock-mode
  548.       (progn
  549.     (remove-hook 'after-change-functions 'font-lock-after-change-function
  550.              t)
  551.     (make-local-hook 'after-change-functions)
  552.     (add-hook 'after-change-functions 'lazy-lock-after-change-function
  553.           nil t))
  554.     (remove-hook 'after-change-functions 'lazy-lock-after-change-function t)
  555.     (if font-lock-mode
  556.     (add-hook 'after-change-functions 'font-lock-after-change-function
  557.           nil t)))
  558. )
  559.  
  560. ;; use put-nonduplicable-text-property to avoid unfriendly behavior
  561. ;; when doing undo, etc.  We really don't want syntax-highlighting text
  562. ;; properties copied into strings or tracked by undo.
  563. ;;
  564. ;; #### If start-open and end-open really behaved like they are supposed to,
  565. ;; we wouldn't really need this.  I kind of fixed them up, but there's still
  566. ;; a bug -- inserting text into the middle of a region of
  567. ;; (start-open t end-open t) text should cause it not to inherit, but it
  568. ;; does.
  569.  
  570. (if lazy-lock-running-xemacs-p
  571.     (defalias 'lazy-lock-put-text-property 'put-nonduplicable-text-property)
  572.   (defalias 'lazy-lock-put-text-property 'put-text-property))
  573.  
  574. (defun lazy-lock-fontify-region (start end &optional buffer)
  575.   "Fontify between START and END in BUFFER where necessary."
  576.   (save-excursion
  577.     (and buffer (set-buffer buffer))
  578.     (save-restriction
  579.       (narrow-to-region start end)
  580.       (let ((lazy-lock-stealth-lines (count-lines start end)))
  581.     (while (text-property-not-all start end 'fontified t)
  582.       (lazy-lock-fontify-stealthily))))))
  583.  
  584. (defun lazy-lock-after-fontify-buffer ()
  585.   ;; Mark the buffer as `fontified'.
  586.   (let ((modified (buffer-modified-p)) (inhibit-read-only t)
  587.     (buffer-undo-list t)
  588.     deactivate-mark buffer-file-name buffer-file-truename)
  589.     (lazy-lock-put-text-property (point-min) (point-max) 'fontified t)
  590.     (or modified (set-buffer-modified-p nil))))
  591.  
  592. ;; Just a cleaner-looking way of coping with Emacs' and XEmacs' `sit-for'.
  593. (defmacro lazy-lock-sit-for (seconds &optional nodisp)
  594.   (if lazy-lock-running-xemacs-p
  595.       (` (sit-for (, seconds) (, nodisp)))
  596.     (` (sit-for (, seconds) 0 (, nodisp)))))
  597.  
  598. ;; Using `save-window-excursion' provokes `window-size-change-functions'.
  599. ;; I prefer `save-walking-excursion', of course, because I have a warped mind.
  600. (if (fboundp 'save-selected-window)
  601.     nil
  602.   (eval-and-compile
  603.     (defmacro save-selected-window (&rest body)
  604.       "Execute the BODY forms, restoring the selected window.
  605. Does not restore the value of point in the selected window, or anything else."
  606.       (` (let ((original-window (selected-window)))
  607.        (unwind-protect
  608.            (progn (,@ body))
  609.          (select-window original-window))))))
  610.   (put 'save-selected-window 'lisp-indent-function 0))
  611.  
  612. ;; Functions for hooks:
  613.  
  614. ;; lazy-lock optimization:
  615. ;;
  616. ;; pre-idle-hook is called an awful lot -- pretty much every time the
  617. ;; mouse moves or a timeout expires, for example.  On Linux (sometimes),
  618. ;; IRIX 5.x, and Solaris 2.something, it happens every 1/4 of a second
  619. ;; due to the 1/4-second timers installed to compensate for various
  620. ;; operating system deficiencies in the handling of SIGIO and SIGCHLD.
  621. ;; (Those timers cause a cycle of the event loop.  They don't necessarily
  622. ;; have to, but rewriting to avoid this is fairly tricky and requires
  623. ;; having significant amounts of code called from signal handlers, which
  624. ;; (despite that fact that FSF Emacs reads its X input during a signal
  625. ;; handler ?!), is almost always a bad idea -- it's extremely easy to
  626. ;; introduce race conditions, which are very hard to track down.
  627. ;;
  628. ;; So to improve things, I added `frame-modified-tick'.  This is an
  629. ;; internal counter that gets ticked any time that any internal
  630. ;; redisplay variable gets ticked.  If `frame-modified-tick' is
  631. ;; the same as the last time we checked, it means that redisplay will
  632. ;; do absolutely nothing when encountering this frame, and thus we
  633. ;; can skip out immediately.  This happens when the 1/4-second timer
  634. ;; fires while we're idle, or if we just move the mouse. (Moving
  635. ;; around in a buffer changes `frame-modified-tick' because the
  636. ;; internal redisplay variable "point_changed" gets ticked.  We could
  637. ;; easily improve things further by adding more tick counters, mirroring
  638. ;; more closely the internal redisplay counters -- e.g. if we had
  639. ;; another counter that didn't get ticked when point moved, we could
  640. ;; tell if anything was going to happen by seeing if point is within
  641. ;; window-start and window-end, since we know that redisplay will
  642. ;; only do a window-scroll if it's not. (If window-start or window-end
  643. ;; or window-buffer or anything else changed, windows_changed or
  644. ;; some other variable will get ticked.))
  645. ;;
  646. ;; Also, it's wise to try and avoid things that cons.  Avoiding
  647. ;; `save-window-excursion', as we do, is definitely a major win
  648. ;; because that's a heavy-duty function as regards consing and such.
  649.  
  650. (defvar lazy-lock-pre-idle-frame-modified-tick nil)
  651. (defvar lazy-lock-pre-idle-selected-frame nil)
  652.  
  653. (defun lazy-lock-pre-idle-fontify-windows ()
  654.   ;; Do groovy things always unless we're in one of the ignored commands.
  655.   ;; The old version did the following five checks:
  656.   ;;
  657.   ;; (a) not in a macro,
  658.   ;; (b) no input pending,
  659.   ;; (c) got a real command (i.e. not an ignored command)
  660.   ;; (d) not in the minibuffer
  661.   ;; (e) no input after waiting for `lazy-lock-continuity-time'.
  662.   ;;
  663.   ;; (a), (b), and (e) are automatically taken care of by `pre-idle-hook'.
  664.   ;;
  665.   ;; Also, we do not have to `set-buffer' and in fact it would be
  666.   ;; incorrect to do so, since we may be being called from
  667.   ;; `accept-process-output' or whatever.
  668.   ;;
  669.   (if (or (memq this-command lazy-lock-ignore-commands)
  670.       (window-minibuffer-p (selected-window)))
  671.       (setq lazy-lock-cache-continue nil)
  672.     (setq lazy-lock-cache-continue t)
  673.     ;; #### we don't yet handle frame-modified-tick on multiple frames.
  674.     ;; handling this shouldn't be hard but I just haven't done it yet.
  675.     (if (or (eq 'all-frames lazy-lock-walk-windows)
  676.         (not (eq lazy-lock-pre-idle-selected-frame (selected-frame)))
  677.         (not (eq lazy-lock-pre-idle-frame-modified-tick
  678.              (frame-modified-tick (selected-frame)))))
  679.     (progn
  680.       ;; Do the visible parts of the buffer(s), i.e., the window(s).
  681.       (if (or (not lazy-lock-walk-windows)
  682.           (and (eq lazy-lock-walk-windows t) (one-window-p t)))
  683.           (if lazy-lock-mode (condition-case nil
  684.                      (lazy-lock-fontify-window)))
  685.         (lazy-lock-fontify-walk-windows))
  686.       (setq lazy-lock-pre-idle-selected-frame (selected-frame))
  687.       (setq lazy-lock-pre-idle-frame-modified-tick
  688.         (frame-modified-tick (selected-frame)))))))
  689.  
  690. (defun lazy-lock-after-change-function (beg end old-len)
  691.   (and lazy-lock-mode
  692.        (if (= beg end)
  693.        (font-lock-after-change-function beg end old-len)
  694.      (lazy-lock-put-text-property beg end 'fontified nil))))
  695.  
  696. ;; DO NOT put this as a pre-idle hook!  The sit-for messes up
  697. ;; mouse dragging.
  698. (defun lazy-lock-post-command-fontify-stealthily ()
  699.   ;; Do groovy things if (a-d) above, (e) not moving the mouse, and (f) no
  700.   ;; input after after waiting for `lazy-lock-stealth-time'.
  701.   (if (and lazy-lock-cache-continue lazy-lock-stealth-time)
  702.       (condition-case data
  703.       (if (lazy-lock-sit-for lazy-lock-stealth-time)
  704.           ;; Do the invisible parts of buffers.
  705.           (lazy-lock-fontify-walk-stealthily)) 
  706.     (error (message "Fontifying stealthily... %s" data)))))
  707.  
  708. ;; In XEmacs 19.14 with pre-idle-hook we do not have to call this.
  709. (defun lazy-lock-post-resize-fontify-windows (frame)
  710.   ;; Fontify all windows in FRAME.
  711.   (let ((lazy-lock-walk-windows t) executing-kbd-macro this-command)
  712.     (save-excursion
  713.       (save-selected-window
  714.     (select-frame frame)
  715.     (lazy-lock-pre-idle-fontify-windows)))))
  716.  
  717. (defun lazy-lock-post-setup-emacs-fontify-windows ()
  718.   ;; Fontify all windows in all frames.
  719.   (let ((lazy-lock-walk-windows 'all-frames) executing-kbd-macro this-command)
  720.     (lazy-lock-pre-idle-fontify-windows)))
  721.  
  722. (defun lazy-lock-post-setup-ediff-control-frame ()
  723.   ;; Fontify all windows in all frames when using the Ediff control frame.
  724.   (make-local-variable 'lazy-lock-walk-windows)
  725.   (setq lazy-lock-walk-windows (if (ediff-multiframe-setup-p) 'all-frames t))
  726.   (lazy-lock-fixup-hooks))
  727.  
  728. ;; Functions for fontification:
  729.  
  730. (defun lazy-lock-fontify-window ()
  731.   ;; Fontify the visible part of the buffer where necessary.
  732.   (let ((ws (if lazy-lock-hide-invisible
  733.         (save-excursion
  734.           (end-of-line) (forward-line (- (window-height))) (point))
  735.           (min (max (window-start) (point-min)) (point-max))))
  736.     (we (if lazy-lock-hide-invisible
  737.         (save-excursion
  738.           (end-of-line) (forward-line (window-height)) (point))
  739.           (min (max (1- (window-end nil t)) (point-min)) (point-max)))))
  740.     (if (or (/= ws lazy-lock-cache-start) (/= we lazy-lock-cache-end))
  741.     ;; Find where we haven't `fontified' before.
  742.     (let* ((start (or (text-property-not-all ws we 'fontified t) ws))
  743.            (end (or (text-property-any start we 'fontified t) we))
  744.            (modified (buffer-modified-p)) (inhibit-read-only t)
  745.            ;; We do the following to prevent: undo list addition; region
  746.            ;; highlight disappearance; supersession/locking checks.
  747.            (buffer-undo-list t)
  748.            deactivate-mark buffer-file-name buffer-file-truename
  749.            ;; Ensure Emacs 19.30 syntactic fontification is always correct.
  750.            font-lock-beginning-of-syntax-function
  751.            ;; Prevent XEmacs 19.13 during fontification from messages.
  752.            font-lock-verbose)
  753.       (while (< start end)
  754.         ;; Fontify and flag the region as `fontified'.
  755.         ;; XEmacs: need to bind `font-lock-always-fontify-immediately'
  756.         ;; or we'll mess up in the presence of deferred font-locking.
  757.         (let ((font-lock-always-fontify-immediately t))
  758.           (font-lock-after-change-function start end 0))
  759.         (lazy-lock-put-text-property start end 'fontified t)
  760.         ;; Find the next region.
  761.         (setq start (or (text-property-not-all ws we 'fontified t) ws)
  762.           end (or (text-property-any start we 'fontified t) we)))
  763.       (setq lazy-lock-cache-start ws lazy-lock-cache-end we)
  764.       (or modified (set-buffer-modified-p nil))))))
  765.  
  766. (defun lazy-lock-fontify-walk-windows ()
  767.   ;; Fontify windows in all required by walking through them.
  768.   (save-excursion
  769.     (save-selected-window
  770.       (condition-case nil
  771.       (walk-windows
  772.        (function (lambda (window)
  773.                (select-window window)
  774.                (if lazy-lock-mode (lazy-lock-fontify-window))))
  775.        'no-minibuf (eq lazy-lock-walk-windows 'all-frames))
  776.     (wrong-type-argument
  777.      ;; Looks like the Emacs 19.28 Garbage Collection bug has hit town.
  778.      ;; Completely remove all text properties and restart.
  779.      (set-text-properties (point-min) (point-max) nil)
  780.      (turn-on-lazy-lock)
  781.      (lazy-lock-fontify-window)
  782.      (message "Fontifying window... done.  (Restarted in %s)"
  783.           (buffer-name)))))))
  784.  
  785. (defun lazy-lock-fontify-stealthily ()
  786.   ;; Fontify an invisible part of the buffer where necessary.
  787.   (save-excursion
  788.     ;; Move to the end in case the character to the left is not `fontified'.
  789.     (end-of-line)
  790.     ;; Find where the next and previous regions not `fontified' begin and end.
  791.     (let ((next (text-property-not-all (point) (point-max) 'fontified t))
  792.       (prev (let ((p (previous-single-property-change (point) 'fontified)))
  793.           (and p (> p (point-min)) p)))
  794.       (modified (buffer-modified-p)) (inhibit-read-only t) start end
  795.       ;; We do the following to prevent: undo list addition; region
  796.       ;; highlight disappearance; supersession/locking checks.
  797.       (buffer-undo-list t)
  798.       deactivate-mark buffer-file-name buffer-file-truename
  799.       ;; Ensure Emacs 19.30 syntactic fontification is always correct.
  800.       font-lock-beginning-of-syntax-function
  801.       ;; Prevent XEmacs 19.13 during fontification from spewing messages.
  802.       font-lock-verbose)
  803.       (cond ((and (null next) (null prev))
  804.          ;; Nothing has been `fontified' yet.
  805.          (beginning-of-line 1) (setq start (point))
  806.          (forward-line (or lazy-lock-stealth-lines (window-height)))
  807.          (setq end (point)))
  808.         ((or (null prev)
  809.          (and next (> (- (point) prev) (- next (point)))))
  810.          ;; The next region is the nearest not `fontified'.
  811.          (goto-char next) (beginning-of-line 1) (setq start (point))
  812.          (forward-line (or lazy-lock-stealth-lines (window-height)))
  813.          ;; Maybe the region is already partially `fontified'.
  814.          (setq end (or (text-property-any next (point) 'fontified t)
  815.                (point))))
  816.         (t
  817.          ;; The previous region is the nearest not `fontified'.
  818.          (goto-char prev) (forward-line 1) (setq end (point))
  819.          (forward-line (- (or lazy-lock-stealth-lines (window-height))))
  820.          ;; Maybe the region is already partially `fontified'.
  821.          (setq start
  822.           (or (previous-single-property-change prev 'fontified nil (point))
  823.           (point)))))
  824.       ;; Fontify and flag the region as `fontified'.
  825.       ;; XEmacs: need to bind `font-lock-always-fontify-immediately'
  826.       ;; or we'll mess up in the presence of deferred font-locking.
  827.       (let ((font-lock-always-fontify-immediately t))
  828.     (font-lock-after-change-function start end 0))
  829.       (lazy-lock-put-text-property start end 'fontified t)
  830.       (or modified (set-buffer-modified-p nil)))))
  831.  
  832. (defun lazy-lock-fontify-walk-stealthily ()
  833.   ;; Fontify regions in all required buffers while there is no input.
  834.   (let ((buffers (buffer-list)) (continue t) fontified message-log-max)
  835.     (save-excursion
  836.       (while (and buffers continue)
  837.     (set-buffer (car buffers))
  838.     (if (and lazy-lock-mode (lazy-lock-unfontified-p))
  839.         ;; Fontify regions in this buffer while there is no input.
  840.         (let ((bufname (buffer-name)))
  841.           (if (and lazy-lock-stealth-verbose (not fontified))
  842.           (message "Fontifying stealthily..."))
  843.           ;; We `save-restriction' and `widen' around everything as
  844.           ;; `lazy-lock-fontify-stealthily' doesn't and we `sit-for'.
  845.           (save-restriction (widen) (lazy-lock-fontify-stealthily))
  846.           (while (and (lazy-lock-unfontified-p)
  847.               (setq continue (lazy-lock-sit-for
  848.                       lazy-lock-stealth-nice)))
  849.         (if lazy-lock-stealth-verbose
  850.             (message "Fontifying stealthily... %2d%% of %s"
  851.                  (lazy-lock-percent-fontified) bufname))
  852.         (save-restriction (widen) (lazy-lock-fontify-stealthily)))
  853.           ;; Note that fontification occurred.
  854.           (setq fontified t)))
  855.     (setq buffers (cdr buffers))))
  856.     (if (and lazy-lock-stealth-verbose fontified)
  857.     (message "Fontifying stealthily... %s." (if continue "done" "quit")))))
  858.  
  859. (defun lazy-lock-unfontified-p ()
  860.   ;; Return non-nil if there is anywhere still to be `fontified'.
  861.   (save-restriction
  862.     (widen)
  863.     (text-property-not-all (point-min) (point-max) 'fontified t)))
  864.  
  865. (defun lazy-lock-percent-fontified ()
  866.   ;; Return the percentage (of characters) of the buffer that are `fontified'.
  867.   (save-restriction
  868.     (widen)
  869.     (let ((size 0) (start (point-min)) (max (point-max)) end)
  870.       (while (setq start (text-property-any start max 'fontified t))
  871.     (setq end (or (text-property-not-all start max 'fontified t) max)
  872.           size (+ size (- end start))
  873.           start end))
  874.       ;; Saying "99% done" is probably better than "100% done" when it isn't.
  875.       (truncate (/ (* size 100.0) (buffer-size))))))
  876.  
  877. (defun lazy-lock-colour-invisible ()
  878.   ;; Fontify the current buffer in `lazy-lock-invisible-face'.
  879.   (save-restriction
  880.     (widen)
  881.     (let ((face 'lazy-lock-invisible-face)
  882.       (fore (if (stringp lazy-lock-invisible-foreground)
  883.             lazy-lock-invisible-foreground
  884.           (cdr (assq 'background-color (frame-parameters)))))
  885.       (modified (buffer-modified-p)) (inhibit-read-only t)
  886.       (buffer-undo-list t)
  887.       deactivate-mark buffer-file-name buffer-file-truename)
  888.       (make-face face)
  889.       (if (not (equal (face-foreground face) fore))
  890.       (condition-case nil
  891.           (set-face-foreground face fore)
  892.         (error (message "Unable to use foreground \"%s\"" fore))))
  893.       (lazy-lock-put-text-property (point-min) (point-max) 'face face)
  894.       (lazy-lock-put-text-property (point-min) (point-max) 'fontified nil)
  895.       (or modified (set-buffer-modified-p nil)))))
  896.  
  897. ;; Functions for Emacs:
  898.  
  899. ;; This fix is for a number of bugs in the function in Emacs 19.28.
  900. (if (and (not lazy-lock-running-xemacs-p)
  901.      (not (emacs-version>= 19 29)))                   
  902.     (defun font-lock-fontify-region (start end &optional loudly)
  903.       "Put proper face on each string and comment between START and END."
  904.       (save-excursion
  905.     (save-restriction
  906.       (widen)
  907.       (goto-char start)
  908.       (beginning-of-line)
  909.       (if loudly (message "Fontifying %s... (syntactically...)" (buffer-name)))
  910.       (let ((inhibit-read-only t) (buffer-undo-list t)
  911.         buffer-file-name buffer-file-truename
  912.         (modified (buffer-modified-p))
  913.         (old-syntax (syntax-table))
  914.         (synstart (if comment-start-skip
  915.                   (concat "\\s\"\\|" comment-start-skip)
  916.                 "\\s\""))
  917.         (comstart (if comment-start-skip
  918.                   (concat "\\s<\\|" comment-start-skip)
  919.                 "\\s<"))
  920.         (startline (point))
  921.         state prev prevstate)
  922.         (unwind-protect
  923.         (progn
  924.           (if font-lock-syntax-table
  925.               (set-syntax-table font-lock-syntax-table))
  926.           ;; Find the state at the line-beginning before START.
  927.           (if (eq startline font-lock-cache-position)
  928.               (setq state font-lock-cache-state)
  929.             ;; Find outermost containing sexp.
  930.             (beginning-of-defun)
  931.             ;; Find the state at STARTLINE.
  932.             (while (< (point) startline)
  933.               (setq state (parse-partial-sexp (point) startline 0)))
  934.             (setq font-lock-cache-state state
  935.               font-lock-cache-position (point)))
  936.           ;; Now find the state precisely at START.
  937.           (setq state (parse-partial-sexp (point) start nil nil state))
  938.           ;; If the region starts inside a string, show the extent of it.
  939.           (if (nth 3 state)
  940.               (let ((beg (point)))
  941.             (while (and (re-search-forward "\\s\"" end 'move)
  942.                     (nth 3 (parse-partial-sexp beg (point) nil nil
  943.                                    state))))
  944.             (lazy-lock-put-text-property
  945.              beg (point) 'face font-lock-string-face)
  946.             (setq state (parse-partial-sexp beg (point)
  947.                             nil nil state))))
  948.           ;; Likewise for a comment.
  949.           (if (or (nth 4 state) (nth 7 state))
  950.               (let ((beg (point)))
  951.             (save-restriction
  952.               (narrow-to-region (point-min) end)
  953.               (condition-case nil
  954.                   (progn
  955.                 (re-search-backward comstart (point-min) 'move)
  956.                 (forward-comment 1)
  957.                 ;; forward-comment skips all whitespace,
  958.                 ;; so go back to the real end of the comment.
  959.                 (skip-chars-backward " \t"))
  960.                 (error (goto-char end))))
  961.             (lazy-lock-put-text-property beg (point) 'face
  962.                              font-lock-comment-face)
  963.             (setq state (parse-partial-sexp beg (point)
  964.                             nil nil state))))
  965.           ;; Find each interesting place between here and END.
  966.           (while (and (< (point) end)
  967.                   (setq prev (point) prevstate state)
  968.                   (re-search-forward synstart end t)
  969.                   (progn
  970.                 ;; Clear out the fonts of what we skip over.
  971.                 (remove-text-properties prev (point) '(face nil))
  972.                 ;; Verify the state at that place
  973.                 ;; so we don't get fooled by \" or \;.
  974.                 (setq state (parse-partial-sexp prev (point)
  975.                                 nil nil state))))
  976.             (let ((here (point)))
  977.               (if (or (nth 4 state) (nth 7 state))
  978.               ;; We found a real comment start.
  979.               (let ((beg (match-beginning 0)))
  980.                 (goto-char beg)
  981.                 (save-restriction
  982.                   (narrow-to-region (point-min) end)
  983.                   (condition-case nil
  984.                   (progn
  985.                     (forward-comment 1)
  986.                     ;; forward-comment skips all whitespace,
  987.                     ;; so go back to the real end of the comment.
  988.                     (skip-chars-backward " \t"))
  989.                 (error (goto-char end))))
  990.                 (lazy-lock-put-text-property
  991.                  beg (point) 'face font-lock-comment-face)
  992.                 (setq state (parse-partial-sexp here (point)
  993.                                 nil nil state)))
  994.             (if (nth 3 state)
  995.                 (let ((beg (match-beginning 0)))
  996.                   (while (and (re-search-forward "\\s\"" end 'move)
  997.                       (nth 3 (parse-partial-sexp
  998.                           here (point) nil nil state))))
  999.                   (lazy-lock-put-text-property
  1000.                    beg (point) 'face font-lock-string-face)
  1001.                   (setq state (parse-partial-sexp here (point)
  1002.                                   nil nil state))))))
  1003.             ;; Make sure PREV is non-nil after the loop
  1004.             ;; only if it was set on the very last iteration.
  1005.             (setq prev nil)))
  1006.           (set-syntax-table old-syntax)
  1007.           (and prev
  1008.            (remove-text-properties prev end '(face nil)))
  1009.           (and (buffer-modified-p)
  1010.            (not modified)
  1011.            (set-buffer-modified-p nil))))))))
  1012.  
  1013. ;; Functions for XEmacs:
  1014.  
  1015. ;; These fix bugs in `text-property-any' and `text-property-not-all'.  They may
  1016. ;; not work perfectly in 19.11 and below because `next-single-property-change'
  1017. ;; is also broke and not easily fixable in Lisp.
  1018. (if (and lazy-lock-running-xemacs-p
  1019.      (not (emacs-version>= 19 12)))
  1020.     (progn
  1021.       ;; Loop through property changes until found.  This fix includes a work
  1022.       ;; around which prevents a bug in `window-start' causing a barf here.
  1023.       (defun text-property-any (start end prop value &optional buffer)
  1024.     "Check text from START to END to see if PROP is ever `eq' to VALUE.
  1025. If so, return the position of the first character whose PROP is `eq'
  1026. to VALUE.  Otherwise return nil."
  1027.     (let ((start (min start end)) (end (max start end)))
  1028.       (while (and start (not (eq (get-text-property start prop buffer) value)))
  1029.         (setq start (next-single-property-change start prop buffer end)))
  1030.       start))
  1031.       ;; No need to loop here; if it's not at START it's at the next change.
  1032.       ;; However, `next-single-property-change' sometimes returns LIMIT, or
  1033.       ;; `point-max', if no change is found and sometimes returns nil.
  1034.       (defun text-property-not-all (start end prop value &optional buffer)
  1035.     "Check text from START to END to see if PROP is ever not `eq' to VALUE.
  1036. If so, return the position of the first character whose PROP is not
  1037. `eq' to VALUE.  Otherwise, return nil."
  1038.     (if (not (eq value (get-text-property start prop buffer)))
  1039.         start
  1040.       (let ((next (next-single-property-change start prop buffer end))
  1041.         (end (or end (save-excursion (and buffer (set-buffer buffer))
  1042.                          (point-max)))))
  1043.         (and next (< next end) next))))))
  1044.  
  1045. ;; XEmacs 19.11 function `font-lock-any-extents-p' looks for `text-prop' rather
  1046. ;; than `face'.  Since `font-lock-unfontify-region' only removes `face', and we
  1047. ;; have non-font-lock properties hanging about, `text-prop' never gets removed.
  1048. ;; Unfortunately `font-lock-any-extents-p' is inlined so we can't redefine it.
  1049. (if (and lazy-lock-running-xemacs-p
  1050.      (not (emacs-version>= 19 12)))
  1051.     (add-hook 'font-lock-mode-hook
  1052.      (function (lambda ()
  1053.     (remove-hook 'after-change-functions 'font-lock-after-change-function)
  1054.     (add-hook 'after-change-functions
  1055.      (function (lambda (beg end old-len)
  1056.         (let ((a-c-beg beg) (a-c-end end))
  1057.           (save-excursion
  1058.         ;; First set `text-prop' to nil for `font-lock-any-extents-p'.
  1059.         (goto-char end) (forward-line 1) (setq end (point))
  1060.         (goto-char beg) (beginning-of-line) (setq beg (point))
  1061.         (lazy-lock-put-text-property beg end 'text-prop nil)
  1062.         ;; Then do the real `font-lock-after-change-function'.
  1063.         (font-lock-after-change-function a-c-beg a-c-end old-len)
  1064.         ;; Now set `fontified' to t to stop `lazy-lock-fontify-window'.
  1065.         (lazy-lock-put-text-property beg end 'fontified t))))))))))
  1066.  
  1067. (if (and lazy-lock-running-xemacs-p (emacs-version>= 19 12))
  1068.     ;; XEmacs 19.12 font-lock.el's `font-lock-fontify-buffer' runs a hook.
  1069.     (add-hook 'font-lock-after-fontify-buffer-hook
  1070.           'lazy-lock-after-fontify-buffer))
  1071.  
  1072. ;; Cope with the differences between Emacs and [LX]Emacs.
  1073. (or (fboundp 'frame-parameters)
  1074.     (defalias 'frame-parameters 'screen-parameters))
  1075.  
  1076. ;; Install ourselves:
  1077.  
  1078. ;; We don't install ourselves on `font-lock-mode-hook' as other packages can be
  1079. ;; used with font-lock.el, and lazy-lock.el should be dumpable without forcing
  1080. ;; people to get lazy or making it difficult for people to use alternatives.
  1081. ;; make sure we add after font-lock's own pre-idle-hook.
  1082. (add-hook 'window-setup-hook 'lazy-lock-post-setup-emacs-fontify-windows)
  1083. ;Not needed in XEmacs 19.14:
  1084. ;(add-hook 'window-size-change-functions 'lazy-lock-post-resize-fontify-windows)
  1085.  
  1086. ;; Package-specific.
  1087. (add-hook 'ediff-after-setup-control-frame-hooks
  1088.       'lazy-lock-post-setup-ediff-control-frame)
  1089.  
  1090. ;; Might as well uninstall too.  Package-local symbols would be nice...
  1091. (and (fboundp 'unintern) (unintern 'lazy-lock-running-xemacs-p))
  1092. (and (fboundp 'unintern) (unintern 'lazy-lock-sit-for))
  1093.  
  1094. ;; Maybe save on the modeline?
  1095. ;;(setcdr (assq 'font-lock-mode minor-mode-alist) '(" Lazy"))
  1096.  
  1097. ;(or (assq 'lazy-lock-mode minor-mode-alist)
  1098. ;    (setq minor-mode-alist (cons '(lazy-lock-mode " Lazy") minor-mode-alist)))
  1099.  
  1100. ;; XEmacs change: do it the right way.  This works with modeline mousing.
  1101. ;;;###autoload
  1102. (add-minor-mode 'lazy-lock-mode " Lazy")
  1103.  
  1104. ;; Provide ourselves:
  1105.  
  1106. (provide 'lazy-lock)
  1107.  
  1108. ;;; lazy-lock.el ends here
  1109.